home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d8 / pdriver5.arc / ISOLAN.ASM < prev    next >
Assembly Source File  |  1989-12-17  |  13KB  |  591 lines

  1. version    equ    1
  2.  
  3.     include    defs.asm    ;SEE ENCLOSED COPYRIGHT MESSAGE
  4.  
  5. ; Packet driver for BICC Data Networks' ISOLAN 4110 ethernet
  6. ; controller, written by
  7. ;    Rainer Toebbicke
  8. ;    European Organisation of Nuclear Research (CERN)
  9. ;    Geneva, Switzerland
  10. ; based on the "generic" packet driver by Russell Nelson.
  11.  
  12.  
  13.  
  14. ; BICC ISOLAN card constants
  15.  
  16. IS_SAP    struc            ;Service Access Point channel
  17. IS_S_Data    db    ?    ;data semaphore
  18. IS_S_Taken    db    ?    ;taken semaphore
  19.         dw    ?
  20.  
  21. IS_S_Event    db    ?
  22.  
  23. IS_S_SrcEaddr    db    6 dup(?)    ;source Ethernet address
  24. IS_S_SrcLsap    db    ?
  25. IS_S_DstEaddr    db    6 dup(?)
  26. IS_S_DstLsap    db    ?
  27.         db    ?
  28. IS_S_Status    dw    ?
  29.         db    ?
  30. IS_S_SDUptr    dw    ?
  31. IS_SAP        ends
  32.  
  33. ; Bits defined in IS_S_Event
  34. IS_M_Init    equ    0ch
  35. IS_M_DataRq    equ    09h
  36. IS_M_DataInd    equ    0ah
  37. IS_Board_Init    equ    0dh
  38.  
  39.  
  40. IS        segment    at 0
  41.         org    8000h
  42. IS_Sign        db    ?        ;test for card presence
  43. IS_Reset    db    ?
  44. IS_Diagok    db    ?
  45. IS_Error    db    ?
  46. IS_ErrCode    db    ?
  47.         org    800eh
  48. IS_PgmStart    dw    ?
  49.  
  50. IS_IER        db    ?        ;interrupt enable register
  51. IS_I_Tx        equ    01h        ;transmit interrupt
  52. IS_I_Rx        equ    02h        ;receive interrupt
  53.  
  54. IS_ISR        db    ?        ;interrupt status reg
  55.         org    8014h
  56. IS_BlueBook    db    ?
  57. IS_LLC1        db    ?
  58. IS_Precv    db    ?        ;promiscuous receive flag
  59. IS_LanceRev    db    ?
  60. IS_MacReflSup    db    ?        ;MAC reflection suppression
  61.         org    8020h
  62. IS_Xmit        IS_SAP    <>        ;Transmit channel
  63.         org    8040h
  64. IS_Rcv        IS_SAP    <>        ;Receive channel
  65.         org    8060h
  66. IS_Eaddr    db    6 dup(?)    ;This card's Ethernet address
  67.  
  68. IS        ends
  69.  
  70.  
  71. IS_SDU        struc
  72. IS_SDU_DataOff    db    ?        ;offset to data
  73. IS_SDU_L    dw    ?        ;length of packet
  74. IS_SDU        ends
  75.  
  76.  
  77. ENET_HDR    equ    EADDR_LEN*2+2    ;length of ethernet header
  78.  
  79.  
  80.  
  81. code    segment    byte public
  82.     assume    cs:code, ds:code
  83.  
  84.     public    int_no,    MemBase
  85. int_no    db    2,0,0,0            ;must be four bytes long for get_number.
  86. MemBase    dw    0b800h,0
  87.  
  88.     public    driver_class, driver_type, driver_name
  89. driver_class    db    1        ;from the packet spec
  90. driver_type    db    4+128        ;from the packet spec
  91. driver_name    db    'ISOLAN',0    ;name of the driver.
  92.  
  93.     public    rcv_modes
  94. rcv_modes    dw    4        ;number of receive modes in our table.
  95.         dw    0,0,0,rcv_mode_3
  96.  
  97.     public    send_pkt
  98. send_pkt:
  99. ;enter with ds:si -> packet, cx = packet length.
  100. ;exit with nc if ok, or else cy if error, dh set to error number.
  101.     assume    ds:nothing
  102.  
  103.     cld                ;moves go forward
  104.     mov    ax,MemBase
  105.     mov    es,ax            ;address the card
  106.     assume    es:IS
  107.     push    cx            ;save length
  108.  
  109. ; Wait for the transmit channel to become free
  110.     mov    cx,0ffffh        ;avoid infinite loop
  111. tx_wait:
  112.     test    IS_Xmit.IS_S_Data,0ffh
  113.     jnz    tx_idle
  114.     loop    tx_wait
  115.     pop    cx            ;remove from stack
  116.     mov    dh,CANT_SEND        ;transmit error
  117.     stc
  118.     ret
  119.  
  120. tx_idle:
  121.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  122.     mov    IS_Xmit.IS_S_Event,IS_M_DataRq    ;sending Data
  123.  
  124. ; copy destination ethernet addr
  125.     mov    cx,EADDR_LEN/2
  126.     lea    di,IS_Xmit.IS_S_DstEaddr
  127.     rep    movsw
  128.  
  129. ; copy source ethernet addr
  130.     mov    cx,EADDR_LEN/2
  131.     lea    di,IS_Xmit.IS_S_SrcEaddr
  132.     rep    movsw
  133.  
  134. ; copy type field
  135.     lodsw
  136.     xchg    ah,al                ;8086 order
  137.     mov    IS_Xmit.IS_S_Status,ax
  138.  
  139.     pop    cx                ;restore count
  140.     sub    cx,ENET_HDR            ;minus header
  141.  
  142.     mov    di,IS_Xmit.IS_S_SDUptr        ;point to SDU
  143.     mov    es:IS_SDU_L[di],cx        ;set count
  144.     xor    ah,ah
  145.     mov    al,es:IS_SDU_DataOff[di]
  146.     add    di,ax                ;point to data
  147.  
  148.     call    movemem                ; now copy the buffer
  149.  
  150.     mov    IS_Xmit.IS_S_Taken,1        ;release channel
  151.     clc                    ;no error occurred
  152.     ret
  153.     assume    es:nothing
  154.  
  155.  
  156. movemem:
  157. ;does the same thing as "rep movsb", only 50% faster.
  158. ;moves words instead of bytes, and handles the case of both addresses odd
  159. ;efficiently.  There is no way to handle one address odd efficiently.
  160. ;This routine always aligns the source address in the hopes that the
  161. ;destination address will also get aligned.  This is from Phil Karn's
  162. ;code from ec.c, a part of his NET package.  I bummed a few instructions
  163. ;out.
  164.     jcxz    movemem_cnte        ; If zero, we're done already.
  165.     test    si,1            ; Does source start on odd byte?
  166.     jz    movemem_adre        ; Go if not
  167.     movsb                ; Yes, move the first byte
  168.     dec    cx            ; Count that byte
  169. movemem_adre:
  170.     shr    cx,1            ; convert to word count
  171.     rep    movsw            ; Move the bulk as words
  172.     jnc    movemem_cnte        ; Go if the count was even
  173.     movsb                ; Move leftover last byte
  174. movemem_cnte:
  175.     ret
  176.  
  177.  
  178.     public    get_address
  179. get_address:
  180. ;get the address of the interface.
  181. ;enter with es:di -> place to get the address, cx = size of address buffer.
  182. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  183.     assume    ds:code
  184.     cmp    cx,EADDR_LEN
  185.     jnb    get_addr_ok        ;buffer ok
  186.     stc
  187.     ret
  188.  
  189. get_addr_ok:
  190.     push    ds
  191.     push    si
  192.     mov    ax,MemBase        ;point to interface
  193.     mov    ds,ax
  194.     assume    ds:IS
  195.  
  196.     mov    si,offset IS_Eaddr    ;point to our E-net addr
  197.     mov    cx,EADDR_LEN/2
  198.     rep    movsw
  199.     pop    si
  200.     pop    ds
  201.     mov    cl,EADDR_LEN
  202.     clc
  203.     ret
  204.  
  205.  
  206.  
  207.     public    set_address
  208. set_address:
  209. ;enter with ds:si -> Ethernet address, CX = length of address.
  210. ;exit with nc if okay, or cy, dh=error if any errors.
  211.     assume    ds:nothing
  212.     cmp    cx,EADDR_LEN
  213.     jnb    set_addr_ok        ;buffer ok
  214.     mov    dh,BAD_ADDRESS
  215.     stc
  216.     ret
  217.  
  218. set_addr_ok:
  219.     push    es
  220.     push    di
  221.     mov    ax,MemBase        ;point to interface
  222.     mov    es,ax
  223.     assume    es:IS
  224.  
  225.     mov    di,offset IS_Eaddr    ;point to our E-net addr
  226.     mov    cx,EADDR_LEN/2
  227.     rep    movsw
  228.  
  229. ; reset the board's software, don't really know if this is needed
  230.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  231.     mov    IS_Xmit.IS_S_Event,IS_Board_Init ;reboot
  232.     mov    IS_Xmit.IS_S_Taken,1        ;issue the command
  233.  
  234. ; wait for request to complete
  235.     mov    cx,0ffffh        ;avoid infinite loop
  236. set_wait_2:
  237.     test    IS_Xmit.IS_S_Data,0ffh
  238.     jnz    set_done
  239.     loop    set_wait_2
  240.  
  241. set_done:
  242.     mov    cx,EADDR_LEN        ;return their address length.
  243.     pop    di
  244.     pop    es
  245.     assume    es:nothing
  246.     clc
  247.     ret
  248.  
  249.  
  250.  
  251. rcv_mode_3:
  252. ;receive mode 3 is the only one we support, so we don't have to do anything.
  253.     ret
  254.  
  255.  
  256.     public    set_multicast_list
  257. set_multicast_list:
  258. ;enter with es:di ->list of multicast addresses, cx = number of bytes.
  259. ;return nc if we set all of them, or cy,dh=error if we didn't.
  260.     mov    dh,NO_MULTICAST
  261.     stc
  262.     ret
  263.  
  264.  
  265.     public    get_multicast_list
  266. get_multicast_list:
  267. ;return with nc, es:di ->list of multicast addresses, cx = number of bytes.
  268. ;return cy, NO_ERROR if we don't remember all of the addresses ourselves.
  269. ;return cy, NO_MULTICAST if we don't implement multicast.
  270.     mov    dh,NO_MULTICAST
  271.     stc
  272.     ret
  273.  
  274.  
  275.     public    reset_interface
  276. reset_interface:
  277. ;reset the interface.
  278.     assume    ds:code
  279.     push    ds
  280.     mov    ax,MemBase
  281.     mov    ds,ax
  282.     assume    ds:IS
  283.     mov    IS_IER,0
  284.     pop    ds
  285.     ret
  286.  
  287.  
  288. ;called when we want to determine what to do with a received packet.
  289. ;enter with cx = packet length, es:di -> packet type.
  290.     extrn    recv_find: near
  291.  
  292. ;called after we have copied the packet into the buffer.
  293. ;enter with ds:si ->the packet, cx = length of the packet.
  294.     extrn    recv_copy: near
  295.  
  296.     extrn    count_in_err: near
  297.     extrn    count_out_err: near
  298.  
  299.     public    recv
  300. recv:
  301. ;called from the recv isr.  All registers have been saved, and ds=cs.
  302. ;Upon exit, the interrupt will be acknowledged.
  303.     assume    ds:code
  304.     mov    ax,MemBase
  305.     mov    ds,ax
  306.     assume    ds:IS
  307.  
  308.     mov    al,IS_ISR        ;get interrupt status
  309.     test    al,IS_I_RX        ;receive interrupt?
  310.     jnz    rcv_test_errors        ;yes...
  311.     jmp    rcv_done
  312.  
  313. rcv_test_errors:
  314.  
  315. ; some thorough testing missing here
  316. ; anyway, don't know what to test
  317.  
  318.  
  319. rcv_no_errors:
  320.     mov    IS_Rcv.IS_S_Data,0    ;block channel
  321.     mov    di,IS_Rcv.IS_S_SDUptr    ;point to SDU
  322.     mov    cx,IS_SDU_L[di]        ;get length
  323.     add    cx,ENET_HDR        ;plus ethernet header
  324.  
  325.  
  326. ; These following lines correctly point to the type field.
  327. ; However, addressability to the whole buffer on the 'receiver' call
  328. ; would be lost, a feature useful to some applications
  329.  
  330. ;    mov     ax,IS_Rcv.IS_S_Status ;get type field
  331. ;    xchg    ah,al         ;in network byte order
  332. ;    push    ax         ;have to place it somewhere
  333. ;    mov    di,sp
  334. ;    push    ss
  335. ;    pop    es            ;es:di at type field
  336.  
  337. ; The following 'hack' keeps addressability to the packet
  338. ; on the 'receiver' call but stays compatible with the
  339. ; packet driver skeleton.
  340. ; This feature is indicated by a bit in the type number (ugly)
  341. ; which the application can examine
  342.  
  343.     mov    al,IS_SDU_DataOff[di]    ;offset to to data
  344.     sub    al,2            ;offset to type field
  345.     cbw
  346.     add    di,ax            ;point to type field
  347.     push    ds
  348.     pop    es            ;es:di->type field
  349.  
  350.     push    cs
  351.     pop    ds            ;don't confuse recv_find
  352.     assume    ds:code
  353.     call    recv_find        ;do we want this packet?
  354. ;    add    sp,2               ;remove type field
  355.  
  356.     mov    ax,es
  357.     or    ax,di
  358.     jz    rcv_done_0        ;pointer zero, give up
  359.  
  360.     push    es
  361.     push    di            ;save pointer
  362.  
  363.     mov    ax,MemBase
  364.     mov    ds,ax
  365.     assume    ds:IS
  366.  
  367. ; set up ethernet header
  368.     mov    cx,EADDR_LEN/2
  369.     mov    si,offset IS_Rcv.IS_S_DstEaddr
  370.     rep    movsw
  371.     mov    cx,EADDR_LEN/2
  372.     mov    si,offset IS_Rcv.IS_S_SrcEaddr
  373.     rep    movsw
  374.     mov    ax,IS_Rcv.IS_S_Status        ;type field
  375.     xchg    ah,al                ;in network byte order
  376.     stosw
  377.  
  378.     mov    si,IS_Rcv.IS_S_SDUptr        ;point to SDU
  379.     mov    cx,IS_SDU_L[si]            ;get length
  380.     push    cx                ;save for later
  381.     mov    al,IS_SDU_DataOff[si]
  382.     xor    ah,ah
  383.     add    si,ax                ;point to data
  384.  
  385.     call    movemem
  386.  
  387.     pop    cx            ;restore count
  388.     pop    si            ;restore pointer
  389.     pop    ds            ;restore pointer
  390.     assume    ds:nothing
  391.  
  392.     add    cx,ENET_HDR        ;adjust length
  393.     call    recv_copy        ;wake up client
  394.  
  395. rcv_done_0:
  396.     mov    ax,MemBase        ;point to interface
  397.     mov    ds,ax
  398.     assume    ds:IS
  399.  
  400. rcv_done:
  401.     mov    IS_Rcv.IS_S_Taken,1    ;release channel
  402.     mov    IS_ISR,0        ;clear interrupt
  403.     push    cs
  404.     pop    ds
  405.     assume    ds:code
  406.     ret
  407.  
  408.  
  409.     public    recv_exiting
  410. recv_exiting:
  411. ;called from the recv isr after interrupts have been acknowledged.
  412. ;Only ds and ax have been saved.
  413.     assume    ds:nothing
  414.     ret
  415.  
  416.  
  417. ;any code after this will not be kept after initialization.
  418. end_resident    label    byte
  419.  
  420.  
  421.     public    usage_msg
  422. usage_msg db "usage: ISOLAN <packet_int_no> <int_level>    <mem_addr>",CR,LF,'$'
  423.  
  424.     public    copyright_msg
  425. copyright_msg    db    "Packet    driver for BICC    ISOLAN device, version ",'0'+version,CR,LF
  426.         db    "Portions Copyright 1989, R.Toebbicke, CERN, Switzerland",CR,LF
  427.  
  428.  
  429. errmsg1    db    "No BICC Isolan    board found at this address.",CR,LF,'$'
  430. diag_errmsg    db    "Error - ISOLAN    Diagnostics failed.$"
  431.  
  432. diag_start_msg    db    "ISOLAN    Diagnostics running... $"
  433. diag_end_msg    db    " done.$"
  434.  
  435. int_no_name    db    "Interrupt number $"
  436. MemBaseName    db    "Shared    Memory address $"
  437. MemPrt    dw    0c000h,0
  438.  
  439.  
  440.  
  441.     extrn    set_recv_isr: near
  442.  
  443. ;enter with si -> argument string, di -> word to store.
  444. ;if there is no number, don't change the number.
  445.     extrn    get_number: near
  446.  
  447.     public    parse_args
  448. parse_args:
  449.     mov    di,offset int_no
  450.     mov    bx,offset int_no_name
  451.     call    get_number
  452.     mov    di,offset MemPrt
  453.     mov    bx,offset MemBaseName
  454.     call    get_number
  455.     mov    di,MemPrt
  456.     sub    di,800h            ;BICC standard notation
  457.     mov    MemBase,di
  458.     ret
  459.  
  460.  
  461. bad_board:
  462.     mov    dx,offset errmsg1
  463. err_msg:
  464.     assume    ds:nothing
  465.     push    cs
  466.     pop    ds
  467.     mov    ah,9
  468.     int    21h
  469.     stc
  470.     ret
  471.  
  472.  
  473.     public    etopen
  474. etopen:
  475.     mov    ax,MemBase
  476.     mov    ds,ax
  477.     assume    ds:IS
  478.  
  479. ; test if board exists
  480.     mov    IS_Sign,42
  481.     cmp    IS_Sign,42
  482.     jne    bad_board
  483.  
  484.     mov    IS_Sign,0ffh-42
  485.     cmp    IS_Sign,0ffh-42
  486.     jne    bad_board
  487.  
  488.     cmp    IS_Reset,01h        ;already running?
  489.     je    diag_ok            ;yes, let it run
  490.  
  491.     mov    IS_Reset,0
  492.     mov    cx,0ffffh        ;avoid infinite loop
  493. diag_w_0:
  494.     cmp    IS_Reset,0fah
  495.     je    diag_1
  496.     loop    diag_w_0
  497.  
  498. diag_1:
  499.     mov    IS_Reset,0ffh
  500.     mov    cx,0ffffh        ;avoid infinite loop
  501. diag_w_1:
  502.     cmp    IS_Reset,0fah
  503.     je    diag_2
  504.     loop    diag_w_1
  505.  
  506. diag_2:
  507.     mov    IS_Reset,0e5h
  508.     mov    cx,0ffffh        ;avoid infinite loop
  509. diag_w_2:
  510.     cmp    IS_Reset,0fah
  511.     je    diag_3
  512.     loop    diag_w_2
  513.  
  514. diag_3:
  515.     mov    IS_Reset,09dh        ;start diagnostics
  516.  
  517.     push    ds
  518.     push    cs
  519.     pop    ds
  520.     mov    dx,offset diag_start_msg
  521.     mov    ah,9
  522.     int    21h
  523.     pop    ds
  524.  
  525.     mov    bx,050h            ;double loop, takes some time
  526. diag_w_3_0:
  527.     mov    cx,0ffffh        ;avoid infinite loop
  528. diag_w_3:
  529.     cmp    IS_Diagok,01h
  530.     je    diag_4
  531.     loop    diag_w_3
  532.     dec    bx
  533.     jnz    diag_w_3_0
  534.     mov    dx,offset diag_errmsg
  535.  
  536. diag_4:
  537.     push    ds
  538.     push    cs
  539.     pop    ds
  540.     mov    dx,offset diag_end_msg
  541.     mov    ah,9
  542.     int    21h
  543.     pop    ds
  544.  
  545.     mov    ax,0800h
  546.     mov    IS_PgmStart,ax
  547.     mov    IS_Reset,01h        ;run the program
  548.  
  549.  
  550. ; enable the board's interrupts
  551. diag_ok:
  552.     push    ds
  553.     push    cs
  554.     pop    ds            ;set cs=ds
  555.     call    set_recv_isr
  556.     pop    ds
  557.  
  558.     mov    IS_BlueBook,1        ;enable Blue Book MAC
  559.     mov    IS_LLC1,1        ;disable LLC1 service
  560.     mov    IS_MacReflSup,1        ;suppress MAC reflection
  561.     mov    IS_IER,IS_I_RX        ;enable for receive
  562.     mov    IS_ISR,0        ;clear previous
  563.  
  564. ; reset the board's software, just in case...
  565.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  566.     mov    IS_Xmit.IS_S_Event,IS_Board_Init ;reboot
  567.     mov    IS_Xmit.IS_S_Taken,1        ;issue the command
  568.  
  569. ; again wait for request to complete
  570.     mov    cx,0ffffh        ;avoid infinite loop
  571. in_wait_2:
  572.     test    IS_Xmit.IS_S_Data,0ffh
  573.     jnz    in_done
  574.     loop    in_wait_2
  575.  
  576. in_done:
  577.  
  578.  
  579. ;if all is okay,
  580.     mov    dx,offset end_resident
  581.     push    cs
  582.     pop    ds
  583.     clc
  584.     ret
  585.  
  586.  
  587.  
  588. code    ends
  589.  
  590.     end
  591.